#include "bsp_uart_stm32f103.h"
#include "bsp_uart_def.h"
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_dma.h"
#include "stm32f1xx_ll_gpio.h"
#include "stm32f1xx_ll_usart.h"
#include "string.h"

static Bsp_THandle g_drv_uart_timer_handle;

static void Drv_UartStartSend_(Bsp_TUartItem* item)
{
    USART_TypeDef* uart = item->cfg->uart_base;
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch = item->cfg->dma_tx_ch;

    item->tx_last_pos = item->tx_pos;

    LL_DMA_DisableChannel(dma, ch);
    LL_DMA_SetDataLength(dma, ch, item->tx_pos);
    LL_DMA_SetMemoryAddress(dma, ch, (UInt32)item->tx_buf);
    LL_DMA_SetPeriphAddress(dma, ch, LL_USART_DMA_GetRegAddr(uart));
    LL_DMA_EnableChannel(dma, ch);
}

static void Drv_UartStopSend_(Bsp_TUartItem* item)
{
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch = item->cfg->dma_tx_ch;

    LL_DMA_DisableChannel(dma, ch);
    item->tx_last_pos = 0;
    item->tx_pos = 0;
    item->is_busy = False;
}

static void Drv_UartStartRecv_(Bsp_TUartItem* item)
{
    USART_TypeDef* uart = item->cfg->uart_base;
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch = item->cfg->dma_rx_ch;

    LL_DMA_SetDataLength(dma, ch, item->rx_buf_size - item->rx_pos);
    LL_DMA_SetMemoryAddress(dma, ch, (UInt32)item->rx_buf + item->rx_pos);
    LL_DMA_SetPeriphAddress(dma, ch, LL_USART_DMA_GetRegAddr(uart));
    LL_DMA_EnableChannel(dma, ch);
}

static void Drv_UartStopRecv_(Bsp_TUartItem* item)
{
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch = item->cfg->dma_rx_ch;

    LL_DMA_DisableChannel(dma, ch);
}

static void Drv_UartSlideData_(Bsp_TUartItem* item)
{
    UInt32 free_size = item->rx_buf_size - item->rx_pos;
    if (free_size < (item->rx_buf_size >> 2))
    {
        free_size = item->rx_buf_size >> 2;
        
        memmove(item->rx_buf, (Int8*)item->rx_buf + item->rx_pos + free_size - item->rx_buf_size, item->rx_buf_size - free_size);
        item->rx_pos = item->rx_buf_size - free_size;
    }
}

static void Drv_UartDmaSendHandle_(Bsp_TUartItem* item)
{
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch_shift = (item->cfg->dma_tx_ch - 1) << 2;
    UInt32 flags = dma->ISR;
    
    if ((flags & (DMA_ISR_TCIF1 << ch_shift)) != 0)
    {
        dma->IFCR = DMA_IFCR_CGIF1 << ch_shift;    ///< 清全局标志

        if (item->on_send != NULL)
        {
            item->on_send(item);
        }

        Int32 size = item->tx_pos - item->tx_last_pos;

        /// 注意：这个写存在bug，先不使用只传输一半的机制
        // if (size > (item->tx_buf_size >> 1))
        //     size = item->tx_buf_size >> 1;


        if (size > 0)
        {
            memmove(item->tx_buf, (Int8*)item->tx_buf + item->tx_last_pos, size);
            item->tx_pos = size;
            __DMB();

            Drv_UartStartSend_(item);
        }
        else
        {
            Drv_UartStopSend_(item);
        }
    }
    else if ((flags & (DMA_ISR_TEIF1 << ch_shift)) != 0)
    {   /// 传输失败
        dma->IFCR = DMA_IFCR_CGIF1 << ch_shift;    ///< 清全局标志

        Int32 size = item->tx_pos - item->tx_last_pos;
        if (size > 0)
        {
            memmove(item->tx_buf, (Int8*)item->tx_buf + item->tx_last_pos, size);
            item->tx_pos = size;

            Drv_UartStartSend_(item);
        }
        else
        {
            Drv_UartStopSend_(item);
        }
    }
}

static void Drv_UartDmaRecvHandle(Bsp_TUartItem* item)
{
    DMA_TypeDef* dma = item->cfg->dma_base;
    UInt32 ch_shift = (item->cfg->dma_rx_ch - 1) << 2;
    UInt32 flags = dma->ISR;

    if ((flags & (DMA_ISR_TCIF1 << ch_shift)) != 0)
    {
        dma->IFCR = DMA_IFCR_CGIF1 << ch_shift;    ///< 清全局标志

        Drv_UartStopRecv_(item);

        item->rx_pos = item->rx_buf_size;

        if (item->on_recv != NULL)
        {
            item->on_recv(item);
        }

        if (item->rx_last_pos != 0)
        {
            memmove(item->rx_buf, (Int8*)item->rx_buf + item->rx_last_pos, item->rx_pos - item->rx_last_pos);
            item->rx_pos = item->rx_pos - item->rx_last_pos;
            item->rx_last_pos = 0;
        }

        Drv_UartSlideData_(item);

        Drv_UartStartRecv_(item);
    }
    else if ((flags & (DMA_ISR_TEIF1 << ch_shift)) != 0)
    {
        dma->IFCR = DMA_IFCR_CGIF1 << ch_shift;    ///< 清全局标志

        Drv_UartStartRecv_(item);
    }
}

static void Drv_UartIrqHandle(Bsp_TUartItem* item)
{
    USART_TypeDef* uart = item->cfg->uart_base;

    if (LL_USART_IsActiveFlag_RXNE(uart))
    {
        LL_USART_ClearFlag_RXNE(uart);
        UInt8 data = LL_USART_ReceiveData8(uart);

        if (item->rx_pos < item->rx_buf_size)
        {
            item->rx_buf[item->rx_pos] = data;
            item->rx_pos++;
        }
        else
        {
            if (item->rx_last_pos != 0)
            {
                memmove(item->rx_buf, (Int8*)item->rx_buf + item->rx_last_pos, item->rx_pos - item->rx_last_pos);
                item->rx_pos = item->rx_pos - item->rx_last_pos;
                item->rx_last_pos = 0;
            }

            Drv_UartSlideData_(item);
            
            item->rx_buf[item->rx_pos] = data;
            item->rx_pos++;
        }
        
        if (item->on_recv != NULL)
        {
            item->on_recv(item);
        }
    }

    if (LL_USART_IsActiveFlag_TXE(uart))
    {
        if (item->on_send != NULL)
        {
            item->on_send(item);
        }

        if (item->tx_last_pos < item->tx_pos)
        {
            uart->DR = item->tx_buf[item->tx_last_pos];
            item->tx_last_pos++;
        }
        else
        {
            item->tx_last_pos = 0;
            item->tx_pos = 0;
            LL_USART_DisableIT_TXE(uart);   ///< 关发送缓冲区空中断
        }
    }
    
    if (LL_USART_IsActiveFlag_PE(uart) || LL_USART_IsActiveFlag_FE(uart) || LL_USART_IsActiveFlag_NE(uart))
    {
        LL_USART_ClearFlag_PE(uart);
        LL_USART_ClearFlag_FE(uart);
        LL_USART_ClearFlag_NE(uart);
    }
}

void DMA2_Channel4_5_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId3];

    Drv_UartDmaSendHandle_(item);
}

void DMA2_Channel3_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId3];

    Drv_UartDmaRecvHandle(item);
}

void DMA1_Channel2_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId2];

    Drv_UartDmaSendHandle_(item);
}

void DMA1_Channel3_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId2];

    Drv_UartDmaRecvHandle(item);
}

void DMA1_Channel4_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId0];

    Drv_UartDmaSendHandle_(item);
}

void DMA1_Channel5_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId0];

    Drv_UartDmaRecvHandle(item);
}

void DMA1_Channel6_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId1];

    Drv_UartDmaRecvHandle(item);
}

void DMA1_Channel7_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId1];

    Drv_UartDmaSendHandle_(item);
}

void UART5_IRQHandler(void)
{
    Bsp_TUartUnion* self =  &g_bsp_uart_union;
    Bsp_TUartItem* item = &self->items[Bsp_kUartId4];
    
    Drv_UartIrqHandle(item);
}

static void MX_USART1_UART_Init(Bsp_TUartItem* item)
{

    /* USER CODE BEGIN USART1_Init 0 */

    /* USER CODE END USART1_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Peripheral clock enable */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);

    /**USART1 GPIO Configuration
     PA9   ------> USART1_TX
    PA10   ------> USART1_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */

    /* USART1_RX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE);

    /* USART1_TX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE);

    /* USER CODE BEGIN USART1_Init 1 */

    /* USER CODE END USART1_Init 1 */
    USART_InitStruct.BaudRate = item->baudrate;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_Init(USART1, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(USART1);
    LL_USART_Enable(USART1);
    /* USER CODE BEGIN USART1_Init 2 */

    /* DMA1_Channel4_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel4_IRQn);
    /* DMA1_Channel5_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel5_IRQn);

    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_5);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_5);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_4);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_4);

    LL_USART_EnableDMAReq_TX(USART1);
    LL_USART_EnableDMAReq_RX(USART1);

    Drv_UartStartRecv_(item);
    /* USER CODE END USART1_Init 2 */

}

static void MX_USART1_Done(Bsp_TUartItem* item)
{
    NVIC_DisableIRQ(DMA1_Channel4_IRQn);
    NVIC_DisableIRQ(DMA1_Channel5_IRQn);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_4);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_4);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_5);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_5);

    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_5);

    LL_USART_DeInit(USART1);
    // NVIC_DisableIRQ(UART4_IRQn);
    LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_USART1);
}

static void MX_USART2_UART_Init(Bsp_TUartItem* item)
{

    /* USER CODE BEGIN USART2_Init 0 */

    /* USER CODE END USART2_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);

    /**USART2 GPIO Configuration
     PA2   ------> USART2_TX
    PA3   ------> USART2_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_3;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
    LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART2 DMA Init */

    /* USART2_RX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE);

    /* USART2_TX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MDATAALIGN_BYTE);

    /* USER CODE BEGIN USART2_Init 1 */

    /* USER CODE END USART2_Init 1 */
    USART_InitStruct.BaudRate = item->baudrate;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_Init(USART2, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(USART2);
    LL_USART_Enable(USART2);
    /* USER CODE BEGIN USART2_Init 2 */

    /* DMA1_Channel6_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel6_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel6_IRQn);
    /* DMA1_Channel7_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel7_IRQn);

    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_7);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_7);

    LL_USART_EnableDMAReq_TX(USART2);
    LL_USART_EnableDMAReq_RX(USART2);

    Drv_UartStartRecv_(item);
    /* USER CODE END USART2_Init 2 */

}

static void MX_USART2_Done(Bsp_TUartItem* item)
{
    NVIC_DisableIRQ(DMA1_Channel6_IRQn);
    NVIC_DisableIRQ(DMA1_Channel7_IRQn);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_7);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_7);

    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_6);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_7);

    LL_USART_DeInit(USART2);
    LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_USART2);
}

static void MX_USART3_UART_Init(Bsp_TUartItem* item)
{

    /* USER CODE BEGIN USART3_Init 0 */

    /* USER CODE END USART3_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);

    /**USART3 GPIO Configuration
     PB10   ------> USART3_TX
    PB11   ------> USART3_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
    LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* USART3 DMA Init */

    /* USART3_RX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_BYTE);

    /* USART3_TX Init */
    LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

    LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE);

    /* USER CODE BEGIN USART3_Init 1 */

    /* USER CODE END USART3_Init 1 */
    USART_InitStruct.BaudRate = item->baudrate;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
    LL_USART_Init(USART3, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(USART3);
    LL_USART_Enable(USART3);
    /* USER CODE BEGIN USART3_Init 2 */

    /* DMA1_Channel2_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel2_IRQn);
    /* DMA1_Channel3_IRQn interrupt configuration */
    NVIC_SetPriority(DMA1_Channel3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA1_Channel3_IRQn);

    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_3);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_3);

    LL_USART_EnableDMAReq_TX(USART3);
    LL_USART_EnableDMAReq_RX(USART3);

    Drv_UartStartRecv_(item);
    /* USER CODE END USART3_Init 2 */

}

static void MX_USART3_Done(Bsp_TUartItem* item)
{
    NVIC_DisableIRQ(DMA1_Channel2_IRQn);
    NVIC_DisableIRQ(DMA1_Channel3_IRQn);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_3);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_3);

    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3);

    LL_USART_DeInit(USART3);
    LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_USART3);
}

static void MX_UART4_Init(Bsp_TUartItem* item)
{
    /* USER CODE BEGIN UART4_Init 0 */

    /* USER CODE END UART4_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Peripheral clock enable */
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART4);
    /**UART4 GPIO Configuration
     PC10   ------> UART4_TX
    PC11   ------> UART4_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* UART4 DMA Init */

    /* UART4_TX Init */
    LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

    LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_5, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_5, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_5, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE);

    /* UART4_RX Init */
    LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

    LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_HIGH);

    LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL);

    LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_3, LL_DMA_PERIPH_NOINCREMENT);

    LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_3, LL_DMA_MEMORY_INCREMENT);

    LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_BYTE);

    LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_BYTE);

    /* UART4 interrupt Init */
    // NVIC_SetPriority(UART4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    // NVIC_EnableIRQ(UART4_IRQn);

    /* USER CODE BEGIN UART4_Init 1 */

    /* USER CODE END UART4_Init 1 */
    USART_InitStruct.BaudRate = item->baudrate;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    LL_USART_Init(UART4, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(UART4);
    LL_USART_Enable(UART4);
    /* USER CODE BEGIN UART4_Init 2 */

    /* DMA interrupt init */
    /* DMA2_Channel3_IRQn interrupt configuration */
    NVIC_SetPriority(DMA2_Channel3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA2_Channel3_IRQn);
    /* DMA2_Channel4_5_IRQn interrupt configuration */
    NVIC_SetPriority(DMA2_Channel4_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);

    LL_DMA_EnableIT_TC(DMA2, LL_DMA_CHANNEL_5);
    LL_DMA_EnableIT_TE(DMA2, LL_DMA_CHANNEL_5);
    LL_DMA_EnableIT_TC(DMA2, LL_DMA_CHANNEL_3);
    LL_DMA_EnableIT_TE(DMA2, LL_DMA_CHANNEL_3);

    LL_USART_EnableDMAReq_TX(UART4);
    LL_USART_EnableDMAReq_RX(UART4);
    
    Drv_UartStartRecv_(item);

    // LL_USART_ClearFlag_RXNE(UART4);
    // LL_USART_ClearFlag_PE(UART4);
    // LL_USART_ClearFlag_FE(UART4);
    // LL_USART_ClearFlag_NE(UART4);
    
    // LL_USART_EnableIT_RXNE(UART4);
    // LL_USART_EnableIT_ERROR(UART4);

    // g_drv_uart_timer_handle = Bsp_TimerCreate();
    
    // Bsp_TimerSetEvent(g_drv_uart_timer_handle, Test_OnTimer);
    // Bsp_TimerStart(g_drv_uart_timer_handle, 1);

    /* USER CODE END UART4_Init 2 */

}

static void MX_UART4_Done(Bsp_TUartItem* item)
{
    NVIC_DisableIRQ(DMA2_Channel3_IRQn);
    NVIC_DisableIRQ(DMA2_Channel4_5_IRQn);
    LL_DMA_DisableIT_TC(DMA2, LL_DMA_CHANNEL_3);
    LL_DMA_DisableIT_TE(DMA2, LL_DMA_CHANNEL_3);
    LL_DMA_DisableIT_TC(DMA2, LL_DMA_CHANNEL_5);
    LL_DMA_DisableIT_TE(DMA2, LL_DMA_CHANNEL_5);

    LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_5);
    LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_3);

    LL_USART_DeInit(UART4);
    NVIC_DisableIRQ(UART4_IRQn);
    LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_UART4);
}

static void MX_UART5_Init(Bsp_TUartItem* item)
{

    /* USER CODE BEGIN UART5_Init 0 */

    /* USER CODE END UART5_Init 0 */

    LL_USART_InitTypeDef USART_InitStruct = {0};

    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5);

    /**UART5 GPIO Configuration
     PC12   ------> UART5_TX
    PD2   ------> UART5_RX
    */
    GPIO_InitStruct.Pin = LL_GPIO_PIN_12;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
    GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
    LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* USER CODE BEGIN UART5_Init 1 */

    /* USER CODE END UART5_Init 1 */
    USART_InitStruct.BaudRate = item->baudrate;
    USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
    USART_InitStruct.Parity = LL_USART_PARITY_NONE;
    USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
    USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    LL_USART_Init(UART5, &USART_InitStruct);
    LL_USART_ConfigAsyncMode(UART5);
    LL_USART_Enable(UART5);
    /* USER CODE BEGIN UART5_Init 2 */

    LL_USART_ClearFlag_RXNE(UART5);
    LL_USART_ClearFlag_PE(UART5);
    LL_USART_ClearFlag_FE(UART5);
    LL_USART_ClearFlag_NE(UART5);
    
    LL_USART_EnableIT_RXNE(UART5);
    LL_USART_EnableIT_ERROR(UART5);
    
    NVIC_SetPriority(UART5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
    NVIC_EnableIRQ(UART5_IRQn);
    /* USER CODE END UART5_Init 2 */

}

static void MX_UART5_Done(Bsp_TUartItem* item)
{
    LL_USART_DeInit(UART5);
    NVIC_DisableIRQ(UART5_IRQn);
    LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_UART5);
}

void Drv_UartOpen(Bsp_TUartItem* item)
{
    switch (item->id)
    {
    case Bsp_kUartId0:
        {
            MX_USART1_UART_Init(item);
        }
        break;
    case Bsp_kUartId1:
        {
            MX_USART2_UART_Init(item);
        }
        break;
    case Bsp_kUartId2:
        {
            MX_USART3_UART_Init(item);
        }
        break;
    case Bsp_kUartId3:
        {
            MX_UART4_Init(item);
        }
        break;
    case Bsp_kUartId4:
        {
            MX_UART5_Init(item);
        }
        break;

    default:
        break;
    }
}

void Drv_UartClose(Bsp_TUartItem* item)
{
    switch (item->id)
    {
    case Bsp_kUartId0:
        {
            MX_USART1_Done(item);
        }
        break;
    case Bsp_kUartId1:
        {
            MX_USART2_Done(item);
        }
        break;
    case Bsp_kUartId2:
        {
            MX_USART3_Done(item);
        }
        break;
    case Bsp_kUartId3:
        {
            MX_UART4_Done(item);
        }
        break;
    case Bsp_kUartId4:
        {
            MX_UART5_Done(item);
        }
        break;

    default:
        break;
    }
}

static void Drv_UartDoSend(Bsp_TUartItem* item)
{
    if (!item->is_busy)
    {
        item->is_busy = True;

        Drv_UartStartSend_(item);
    }
}

Int32 Drv_UartRead(Bsp_TUartItem* item, void *buf, UInt32 size)
{
    __disable_irq();

    if (item->cfg->is_dma)
    {
        // Drv_UartStopRecv_(item);

        UInt32 remain_size = LL_DMA_GetDataLength(item->cfg->dma_base, item->cfg->dma_rx_ch);
        item->rx_pos = item->rx_buf_size - remain_size;

        UInt32 readable_size = item->rx_pos - item->rx_last_pos;
        if (size > readable_size)
            size = readable_size;
        if (size > 0)
        {
            memcpy(buf, item->rx_buf + item->rx_last_pos, size);
            item->rx_last_pos += size;
        }

        // Drv_UartSlideData_(item);

        // Drv_UartStartRecv_(item);
    }
    else
    {
        UInt32 readable_size = item->rx_pos - item->rx_last_pos;
        if (size > readable_size)
            size = readable_size;
        if (size > 0)
        {
            memcpy(buf, item->rx_buf + item->rx_last_pos, size);
            item->rx_last_pos += size;
        }
    }

    __enable_irq();

    return size;
}

Int32 Drv_UartWrite(Bsp_TUartItem* item, const void *data, UInt32 size)
{
    __disable_irq();

    if (item->cfg->is_dma)
    {
        UInt32 writable_size = item->tx_buf_size - item->tx_pos;
        if (size > writable_size)
            size = writable_size;
        if (size > 0)
        {
            memcpy((Int8*)item->tx_buf + item->tx_pos, data, size);
            item->tx_pos = item->tx_pos + size;
            
            Drv_UartDoSend(item);
            
            __DMB();
        }
    }
    else
    {
        UInt32 writable_size = item->tx_buf_size - item->tx_pos;
        if (size > writable_size)
            size = writable_size;
        if (size > 0)
        {
            memcpy((Int8*)item->tx_buf + item->tx_pos, data, size);
            item->tx_pos = item->tx_pos + size;
            LL_USART_EnableIT_TXE(item->cfg->uart_base);
        }
    }

    __enable_irq();
    
    return size;
}

Int32 Drv_UartReadableCount(Bsp_TUartItem* item)
{
    if (item->cfg->is_dma)
    {
        UInt32 remain_size = LL_DMA_GetDataLength(item->cfg->dma_base, item->cfg->dma_rx_ch);
        item->rx_pos = item->rx_buf_size - remain_size;
    }

    return item->rx_pos - item->rx_last_pos;
}

// void UART4_IRQHandler(void)
// {
//     Bsp_TUartUnion* self =  &g_bsp_uart_union;
//     Bsp_TUartItem* item = &self->items[Bsp_kUartId3];

//     // if (LL_USART_IsActiveFlag_RXNE(UART4))
//     // {
//     //     LL_USART_ClearFlag_RXNE(UART4);

//     //     if (item->rx_pos < item->rx_buf_size)
//     //     {
//     //         item->rx_buf[item->rx_pos] = LL_USART_ReceiveData8(UART4);
//     //         item->rx_pos++;
//     //     }
//     // }
//     // else 
//     if (LL_USART_IsActiveFlag_PE(UART4) || LL_USART_IsActiveFlag_FE(UART4) || LL_USART_IsActiveFlag_NE(UART4))
//     {
//         LL_USART_ClearFlag_PE(UART4);
//         LL_USART_ClearFlag_FE(UART4);
//         LL_USART_ClearFlag_NE(UART4);
//     }
// }
